/* ipfw.h - ipfw hook header file */

/* Copyright 2004 Wind River Systems, Inc. */

/*
modification history
--------------------
01f,12apr05,nee  Replace _KERNEL with _WRS_KERNEL
01e,19jul04,vvv  fixed warning
01d,15jul04,sar  Remove some leftover code
01c,13jul04,sar  Correct kernel define and update IPFW_HOOK to avoid
                 triggering errors from some compilers.
01b,22jun04,sar  Update flags and cleanup unneeded stuff
01a,25may04,sar  Created initial version
*/

/*-
 * Copyright (c) 1996,1997 Berkeley Software Design, Inc.
 * All rights reserved.
 * The Berkeley Software Design Inc. software License Agreement specifies
 * the terms and conditions for redistribution.
 *
 *	BSDI $Id: ipfw.h,v 2.20 2002/12/20 16:10:30 prb Exp $
 */

/*
 * Return values from ip filters using bpf
 *
 * Certain combinations do not make sense:
 * IPFW_ICMP, IPFW_ACCEPT, and IPFW_CONTROL are mutually exclusive.
 * When used as a return value back to IP, only IPFW_REJECT, IPFW_ACCEPT
 * and IPFW_NEXT make sense.
 * When IPFW_REJECT is sent to IP, the IPFW_SIZE bits contain the ICMP code
 * (upper 8 bits) and type (lower 8 bits), if any.
 * IPFW_CONTROL is only sent to user level daemons watching us.
 *
 * In the Wind River version we have changed the IP calling conventions.
 * In our code we loop through the list of filters in the IP stack rather
 * than having each filter call the next in the list.  To handle this
 * we include NEXT as a valid return value and use the previous value of
 * SKIPPED for it.  Currently we only use the REJECT, ACCEPT and NEXT bits
 * the rest are included to allow us to use mostly the same bits if we
 * expand our version in the future.
 *
 */

#ifndef __INCipfwh
#define __INCipfwh

#define	IPFW_REJECT	0x00000000	/* Packet was rejected */
#define	IPFW_ACCEPT	0x80000000	/* Packet was accepted */
#define	IPFW_REPORT	0x40000000	/* Reports this packet to user level */
#define	IPFW_CONTROL	0x20000000	/* A control message of sorts */
#define	IPFW_ICMP	0x20000000	/* Send back an ICMP message */
#define	IPFW_NEXT	0x10000000	/* Pass on to the next filter */
#define	IPFW_RETCODE	0xf0000000	/* valid bits in return code */
#define	IPFW_SIZE	0x0000ffff	/* Number of bytes to send upward */
#define	IPFW_ICMPTYPE	0x0000ff00	/* ICMP type to return */
#define	IPFW_ICMPCODE	0x000000ff	/* ICMP code to return */
#define	IPFW_USER	0x00ff0000	/* bits available to user */
#define	IPFW_FILTER	0x0f000000	/* Mask of the filter bits */

/*
 * Filters 1 - 14 can be defined.
 * 0 and 15 are magic
 */
#define	IPFW_PREINPUT	(1 << 24)
#define	IPFW_INPUT	(2 << 24)
#define	IPFW_FORWARD	(3 << 24)
#define	IPFW_PREOUTPUT	(4 << 24) /* not currently used */
#define	IPFW_OUTPUT	(5 << 24)
#define	IPFW_CALL	(6 << 24) /* not currently used */
#define	IPFW_RATE	(7 << 24) /* not currently used */
#define	IPFW_PREINPUT6	(8 << 24)
#define	IPFW_INPUT6	(9 << 24)
#define	IPFW_FORWARD6	(10 << 24)
#define	IPFW_PREOUTPUT6	(11 << 24) /* not currently used */
#define	IPFW_OUTPUT6	(12 << 24)

/*
 * Our socket options
 */
#define	IPFW_SELECT	0x01	/* Set/get the selection mask */

/*
 * Several of the BPF memory locations are pre-loaded as follows:
 */
#define	IPFWM_AUX	0		/* aux return value for errors */
#define	IPFWM_SRCIF	1		/* source interface index */
#define	IPFWM_DSTIF	2		/* destination interface index */
#define	IPFWM_SRCRT	3		/* interface to route back to source */
#define	IPFWM_MFLAGS	4		/* mbuf flags */
#define	IPFWM_EXTRA	5		/* extra headers in front of packet */
#define	IPFWM_POINT	6		/* what filter point we came from */
#define	IPFWM_DSTADDR	7		/* routing destination address */

#define	IPFWM_MAX	8

/*
 * sysctl values for NET.INET.IP.IPFW.which.command
 * 
 * Not all of these values are currently used.  They are included for
 * potential compatibility with other versions of the IPFW code
 */
#define	IPFWCTL_PUSH		1	/* push on BPF filters/checksums */
#define	IPFWCTL_FLAGS		2	/* return the flags */
#define	IPFWCTL_SECURE		3	/* dont allow filter to change */
#define	IPFWCTL_FORW		4	/* apply to forwarded packets too */
#define	IPFWCTL_STATS		5	/* gather filter statistics */
#define	IPFWCTL_POP		6	/* pop off specified filters */
#define	IPFWCTL_POPALL		7	/* pop off all filters here and below */
#define	IPFWCTL_SERIAL		8	/* get the next serial number */
#define	IPFWCTL_SYSCTL		9	/* call the filter specific sysctl */
#define	IPFWCTL_INSERT		10	/* insert into filter call list */
#define	IPFWCTL_RATEFILTER	11	/* apply a rate filter to an ifnet */
#define	IPFWCTL_MOVE		12	/* move filters in a chain */
#define	IPFWCTL_LIST		13	/* list all filters in a chain */
#define	IPFWCTL_CLEAN		14	/* clean a call filter entry */
#define	IPFWCTL_CALLFILTERS	15	/* list all filters in call chain */

/*
 * Options for the list commands
 */

#define IPFW_CONCISE 0
#define IPFW_VERBOSE 1

/*
 * Flags, see below
 */
#define	IPFWF_MODIFY	0x0001	/* filter can modify the packet */
#define	IPFWF_DONTFREE	0x0002	/* do not free the packet on reject */
#define	IPFWF_CALL	0x0004	/* need to set up the call list */
#define	IPFWF_NEXTOK	0x0008	/* if we next off the chain, accept pkt*/
#define	IPFWF_ICMPOK	0x0010	/* filter can send icmp errors, not
                                   yet implemented */
#define	IPFWF_FILTER1	0x1000	/* filter specific bit 1 */
#define	IPFWF_FILTER2	0x2000	/* filter specific bit 2 */
#define	IPFWF_FILTER3	0x4000	/* filter specific bit 3 */
#define	IPFWF_FILTER4	0x8000	/* filter specific bit 4 */
#define	IPFWF_FILTERM	0xf000	/* filter specific bits */

/*
 * We define some macros here to include the optional flags passed in.
 * They are passed along with the filter type. 
 */
#define IPFW_PREINPUTv4	(IPFW_PREINPUT|IPFWF_MODIFY|IPFWF_NEXTOK|IPFWF_ICMPOK) 
#define IPFW_INPUTv4	(IPFW_INPUT   | IPFWF_ICMPOK)
#define IPFW_FORWARDv4	(IPFW_FORWARD | IPFWF_MODIFY | IPFWF_ICMPOK)
#define IPFW_OUTPUTv4	(IPFW_OUTPUT  | IPFWF_MODIFY)

#define IPFW_PREINPUTv6	(IPFW_PREINPUT6 | IPFWF_MODIFY | IPFWF_NEXTOK) 
#define IPFW_INPUTv6	(IPFW_INPUT6)
#define IPFW_FORWARDv6	(IPFW_FORWARD6  | IPFWF_MODIFY)
#define IPFW_OUTPUTv6	(IPFW_OUTPUT6   | IPFWF_MODIFY)

/*
 * types of blocks we can send into sysctl
 * 
 * Most of this list is inherited from previous versions of IPFW.  They
 * have been included for potential compatibility.
 */
#define	IPFW_BPF	1		/* BPF based filter follows */
#define	IPFW_CISCO	2		/* Cisco based filter follows */
#define	IPFW_CHECKSUM	3		/* cryptographic checksum follows */
#define	IPFW_PASSWORD	4		/* password to checksum follows */
#define	IPFW_CIRCUIT	5		/* Circuit cache filter follows */
#define	IPFW_FLOW	6		/* Flow monitor filter follows */
#define	IPFW_NAT	7		/* NAT table */
#define	IPFW_THROTTLE	8		/* Throttle filter */
#define	IPFW_CACHE	9		/* Cache lookup (filter) */
#define	IPFW_ECHOCHK	10		/* ICMP echo (filter) */
#define	IPFW_REWRITE	11		/* IP Rewrite (filter) */
#define IPFW_IPSEC      12              /* IP Security filter */
#define IPFW_FIREWALL   13              /* Firewall Filter */

#define	IPFW_TAGLEN	32		/* Allow 32 character ascii tag */

/*
 * Header that preceeds any part of a filter
 */
typedef struct {
	int		type;		/* Type of block (see above) */
	size_t		hlength;	/* Length of this header */
	size_t		length;		/* Length of data after header */
	int		serial;		/* Our serial number */
	int		priority;	/* Our priority */
	char		tag[IPFW_TAGLEN];
} ipfw_filter_t;

#define	IPFW_round(x)	(((x) + sizeof(int) - 1) & ~(sizeof(int)-1))
#define	IPFW_len(s)	IPFW_round((s)->length)
#define	IPFW_next(s)	(((u_char *)(s) + s->hlength) + IPFW_len(s))

typedef struct {
	u_int	mask;
	u_int	code;
} ipfw_data_t;

typedef struct {
	u_short	version;	/* version number */
	u_short	hdrlen;		/* length of header */
	u_long	length;		/* length of packet */
	u_int	code;		/* code word */
	struct	timespec when;	/* when the packet came in */
} ipfw_hdr_t;

#define	IPFW_VER_1_0	0x0100	/* First version (with version numbers) */

typedef struct ipfw_opt_t {
	u_long	bits;
	int	extra;
	struct	mbuf *mbuf;
	struct	ifnet *dstifp;
	u_int32_t dstaddr;
} ipfw_opt_t;

#define	IPFWB_EXTRA	0x0001	/* Extra value is included */
#define	IPFWB_DSTIF	0x0002	/* Destination IFP is included */
#define	IPFWB_MBUF	0x0004	/* Mbuf was replaced (return) */
#define	IPFWB_DSTADDR	0x0008	/* New routing destination (return) */

#define	ioptchk(iopt,bit)	((iopt) && ((iopt)->bits) & bit)
#ifdef	_WRS_KERNEL

/* Forward reference */
struct ipfw_anchor_t;

/* The structure for holding information about a given instance
   of a filter */
typedef struct ipfw_t {
	int	type;
	int	serial;
	int	priority;
	char	tag[IPFW_TAGLEN];
	u_long	(*filter) __P((struct ipfw_t *, struct mbuf **,
                               int *, ipfw_opt_t *));
	void	(*free)   __P((struct ipfw_t *));
	int	(*get)    __P((struct ipfw_t *, void *, size_t *, size_t *));
	int	(*push)   __P((struct ipfw_t *, void *, size_t));
	int	(*sysctl) __P((struct ipfw_t *, int *, u_int, void *,
                               size_t *, void *, size_t));
	int	              len; /* length of filter
                                      (for return on sysctl) */
        struct ipfw_anchor_t *parent;
	struct ipfw_t        *next;
	struct ipfw_t        *prev;
	void	             *private;
} ipfw_t;

typedef struct ipfw_t IPFW_T;

typedef struct ipfw_stats_t {
	quad_t	dropped;	/* packets dropped by filter */
	quad_t	denied;		/* packets dropped & reported by filter */
	quad_t	accepted;	/* packets accepted by filter */
	quad_t	reported;	/* packets accepted & reported by filter */
	quad_t	reportfailed;	/* packets where reported failed by filter */
	quad_t	unknown;	/* packets where reported failed by filter */
} ipfw_stats_t;

/* The structure for holding the anchor for a list of filters.
   One of these is created for each point at which we want to
   be able to invoke filters.  */
typedef	struct ipfw_anchor_t {
        ipfw_t       *filter_list; /* pointer to list of filters */
        ipfw_stats_t  stats;       /* space for the statistics */
} ipfw_anchor_t;

/* The structure to map from a type to a routine to create a filter
   of that type and install it into one of our lists.  What information
   each filter needs is up to that class of filter. */
#define IPFW_MAX_PUSH_POINTS 32
typedef int (*IPFW_PUSH_FUNCPTR) (struct ipfw_t *, void *, size_t);
typedef struct {
	int	          type;
	IPFW_PUSH_FUNCPTR push;
} ipfw_type_t;

#ifndef VIRTUAL_STACK
extern int ipfw_serial;

extern ipfw_anchor_t ipfw_input;
extern ipfw_anchor_t ipfw_forward;
extern ipfw_anchor_t ipfw_output;
extern ipfw_anchor_t ipfw_preinput;
extern ipfw_anchor_t ipfw_call;
extern ipfw_anchor_t ipfw_rate;
extern ipfw_type_t ipfw_types[];

#ifdef INET6
extern ipfw_anchor_t ipfw_input6;
extern ipfw_anchor_t ipfw_forward6;
extern ipfw_anchor_t ipfw_output6;
extern ipfw_anchor_t ipfw_preinput6;
#endif

#if 0
/* These aren't currently implemented */
extern ipfw_call_t *ipfw_filters;
extern int ipfw_nfilters;
#endif 

#endif /* VIRTUAL_STACK */

void ipfwInit __P((void));

#ifdef INET6
void ipfw6Init __P((void));
#endif

int ipfwSysctl __P((int *, u_int, void *, size_t *, void *, size_t));
int ipfwPushRegister __P((int, IPFW_PUSH_FUNCPTR));

#define	NULL_DAP	((struct in_addr *)0)

#define	IPFW_HOOK(_ipf, _mp, _dir, _bits, _difp, _extra, _dap, _res, _iopt) \
{ \
  int argBits = _bits; \
		       \
  (_iopt)->bits = (argBits) & ~IPFWB_DSTADDR; \
  if ((argBits) & IPFWB_DSTIF) \
    {(_iopt)->dstifp = _difp; } \
  else \
    {(_iopt)->dstifp = 0; } \
  *_res = ((_ipf)->filter)(_ipf, _mp, _dir, _iopt) & IPFW_RETCODE; \
  if (((argBits) & IPFWB_DSTADDR) && \
      (((_iopt)->bits & IPFWB_DSTADDR) != 0)) \
      {(_dap)->s_addr = (_iopt)->dstaddr; } \
}

#endif


#if 0 
/* The following items haven't been ported or used yet */

/*
 * Call the next filter in the chain, but only if we are not on the call chain.
 */
#define	NEXTFILTER(filterp, m, dir, iopt) do { \
	if ((dir & IPFWF_CALL) == 0 && filterp->next) \
		return(filterp->next->filter(filterp->next, m, dir, iopt)); \
} while (0)


/*
 * The ipfw_call_t struct contains the list of filters on the
 * call chain.  There can be at most 64K at one time.
 * The reference index is actually (index | (generation << 16)).
 * This allows the calling filter to know if it is calling the
 * correct filter or not.
 *
 * This structure is also used to report the call chain back to user
 * level so that an association between tag and index number can be made.
 */
typedef struct {
	u_short	generation;		/* what generation we are */
	u_short	index;			/* our index number for reporting */
	char	tag[IPFW_TAGLEN];	/* last tag to hold this index */
#ifdef	KERNEL
	ipfw_t	*filter;		/* current filter holding index */
#else
	void	*filter;
#endif
} ipfw_call_t;

void ipfw_log __P((struct mbuf *, u_int, struct ifnet *, ipfw_stats_t *));

#endif /* #if 0 */
#endif /* __INCipfwh */



